package com.jrx.anytxn.transaction.service.impl;
import java.util.Date;

import com.jrx.anytxn.common.constant.CommonContants;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.function.UncheckedUnaryOperator;
import com.jrx.anytxn.common.uitl.BeanMapping;
import com.jrx.anytxn.common.uitl.CollectorsUtils;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.customer.bean.MarketingRecordCreationBean;
import com.jrx.anytxn.customer.constant.CustomerConstant;
import com.jrx.anytxn.customer.dto.customer.CustomerFirstLevelRes;
import com.jrx.anytxn.customer.dto.customer.CustomerSecondLevelRes;
import com.jrx.anytxn.customer.entity.*;
import com.jrx.anytxn.customer.mapper.ext.ExtCmCustomerAddressInfoMapper;
import com.jrx.anytxn.customer.mapper.ext.ExtCmCustomerLimitInfoMapper;
import com.jrx.anytxn.customer.mapper.ext.ExtCmCustomerRightInfoMapper;
import com.jrx.anytxn.customer.mapper.ext.ExtTlMarketingRecordMapper;
import com.jrx.anytxn.customer.service.ICustomerLimitInfoService;
import com.jrx.anytxn.customer.service.ICustomerRightService;
import com.jrx.anytxn.customer.service.ICustomerService;
import com.jrx.anytxn.number.exception.SegmentException;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.dto.aviator.RuleMatchReq;
import com.jrx.anytxn.param.entity.*;
import com.jrx.anytxn.param.enums.BizTypeEnum;
import com.jrx.anytxn.param.service.aviator.IAviatorService;
import com.jrx.anytxn.param.service.product.IInterestTableService;
import com.jrx.anytxn.param.service.product.IProductTableService;
import com.jrx.anytxn.param.service.rights.IPrPromotionInfoService;
import com.jrx.anytxn.param.service.system.IChannelTableService;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.param.utils.BizTypeProducts;
import com.jrx.anytxn.transaction.bean.*;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.dto.common.DisbursementLogRes;
import com.jrx.anytxn.transaction.dto.common.RepaymentPlanInfoRes;
import com.jrx.anytxn.transaction.dto.loan.*;
import com.jrx.anytxn.transaction.entity.*;
import com.jrx.anytxn.transaction.mapper.base.AmLoanAccountInfoMapper;
import com.jrx.anytxn.transaction.mapper.base.AmLoanMainInfoMapper;
import com.jrx.anytxn.transaction.mapper.base.TlDisbursementLogMapper;
import com.jrx.anytxn.transaction.mapper.ext.*;
import com.jrx.anytxn.transaction.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;

@Service
public class LoanServiceImpl implements ILoanService {

    private static final Logger logger = LoggerFactory.getLogger(LoanServiceImpl.class);

    @Resource
    private AmLoanMainInfoMapper amLoanMainInfoMapper;
    @Resource
    private ExtAmLoanMainInfoMapper extAmLoanMainInfoMapper;
    @Resource
    private ExtAmAccountMainInfoMapper extAmAccountMainInfoMapper;
    @Resource
    private ExtAmInterestAccrualInfoMapper extAmInterestAccrualInfoMapper;
    @Resource
    private TlDisbursementLogMapper tlDisbursementLogMapper;
    @Resource
    private ExtTlDisbursementLogMapper extTlDisbursementLogMapper;
    @Resource
    private ExtAmRepaymentPlanInfoMapper extAmRepaymentPlanInfoMapper;
    @Autowired
    private IAccountService accountService;
    @Autowired
    private ILoanMainInfoService loanMainInfoService;
    @Autowired
    private IGlInterfaceService glInterfaceService;
    @Autowired
    private IRepaymentPlanService repaymentPlanService;
    @Autowired
    private ILoanAccountMainInfoService loanAccountMainInfoService;
    @Resource
    private AmLoanAccountInfoMapper amLoanAccountInfoMapper;
    @Autowired
    private IDisbursementLogService disbursementLogService;
    @Resource
    private ExtAmLoanAccountInfoMapper extAmLoanAccountInfoMapper;
    @Resource
    private ExtTlGlInterfaceInfoMapper extTlGlInterfaceInfoMapper;
    @Autowired
    private ITlTransactionInfoService tlTransactionInfoService;
    @Resource
    private ExtTlTransactionInfoMapper extTlTransactionInfoMapper;
    @Autowired
    private ICustomerService customerService;
    @Autowired
    private IInterestTableService interestTableService;
    @Resource
    private ExtAmWaiveRepaymentPlanInfoMapper extAmWaiveRepaymentPlanInfoMapper;
    @Autowired
    private IProductTableService productTableService;
    @Autowired
    private IChannelTableService channelTableService;
    @Autowired
    private IInterestCalculateService interestCalculateService;
    @Resource
    private ExtTlInterestAccrualLogMapper extTlInterestAccrualLogMapper;
    @Autowired
    private IOrganizationTableService organizationTableService;
    @Autowired
    private ICustomerLimitInfoService customerLimitInfoService;
    @Autowired
    private IAviatorService aviatorService;
    @Autowired
    private ICustomerRightService customerRightService;
    @Resource
    private ExtCmCustomerAddressInfoMapper extCmCustomerAddressInfoMapper;
    @Autowired
    private ISegmentService segmentService;
    @Resource
    private ExtTlMarketingRecordMapper extTlMarketingRecordMapper;
    @Resource
    private ExtCmCustomerLimitInfoMapper extCmCustomerLimitInfoMapper;
    @Autowired
    private IPrPromotionInfoService prPromotionInfoService;
    @Resource
    private ExtCmCustomerRightInfoMapper extCmCustomerRightInfoMapper;
    @Autowired
    private ISmsService smsService;

    @Override
    public LoanConfirmRes generatingOrderRelationInfo(LoanParamBean loanParamBean, LoanConfirmReq loanConfirmReq) throws Exception {
        //业务日期
        Date businessDate = loanParamBean.getOrg().getNextProcessingDate();
        logger.debug("构建贷款订单");
        AmLoanMainInfo amLoanMainInfo = loanMainInfoService.buildLoanMainInfo(loanParamBean, loanConfirmReq, businessDate);

        logger.debug("构建贷款账户信息");
        AmLoanAccountInfo amLoanAccountInfo = loanAccountMainInfoService.buildAmLoanAccountInfo(amLoanMainInfo);

        String liabilityFlag = TransBizConstant.LIABILITY_FLAG_00;
        PrWaiveInterestTable prWaiveInterestTable = loanParamBean.getPrWaiveInterestTable();
        if (StringUtils.isNotBlank(loanParamBean.getWaiveInterestId())) {
            liabilityFlag = prWaiveInterestTable.getInterestDiscountPayer();
        }

        logger.debug("构建总账流水");
        List<TlGlInterfaceInfo> glInterfaceInfoList = new ArrayList<>();
        List<TlTransactionInfo> transactionInfoList = new ArrayList<>();
        TlGlInterfaceInfo tlGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(amLoanMainInfo,
                amLoanAccountInfo, loanParamBean.getProduct().getChineseName(), businessDate, liabilityFlag);
        if (null != tlGlInterfaceInfo) {
            glInterfaceInfoList.add(tlGlInterfaceInfo);
        }

        //20200515 只有下单放款的订单才生成支付流水
        PrProductTable prProductTable = loanParamBean.getProduct();

        //是否为受托支付
        String entrustedPayment = loanConfirmReq.getEntrustedPayment();

        if (TransBizConstant.YES_FLAG.equals(prProductTable.getRemitWhenLoan())) {
            logger.debug("构建支付流水信息");
            TlDisbursementLog tlDisbursementLog = disbursementLogService.buildTlDisbursementLog(amLoanMainInfo,
                    loanParamBean.getCustomer(), loanParamBean.getCustomerBank(), prProductTable, businessDate);
            tlDisbursementLog.setEntrustedPayment(entrustedPayment);
            //如果为受托支付
            if (TransBizConstant.YES_FLAG.equals(entrustedPayment)) {
                tlDisbursementLog.setPayeeBankName(loanConfirmReq.getPayeeBankName());
                tlDisbursementLog.setPayeeAccount(loanConfirmReq.getCardNumber());
                tlDisbursementLog.setPayeeName(loanConfirmReq.getPayeeName());
                tlDisbursementLog.setPayeeBank(loanConfirmReq.getPayeeBank());
            }
            if (Objects.nonNull(tlGlInterfaceInfo)) {
                tlGlInterfaceInfo.setBankType(TransBizConstant.CARD_TYPE_0);
                if (Objects.equals(tlDisbursementLog.getPayeeAccountType(),(TransBizConstant.CARD_TYPE_1))) {
                    tlGlInterfaceInfo.setBankType(TransBizConstant.CARD_TYPE_1);
                }
            }
            //放款流水入库
            tlDisbursementLogMapper.insertSelective(tlDisbursementLog);

//            //生成交易信息
////            TlTransactionInfo tlTransactionInfo = tlTransactionInfoService.buildTlTransactionInfo(tlDisbursementLog,
////                    TransBizConstant.TRANSCATION_REVERSAL_FLAG_0);
////            transactionInfoList.add(tlTransactionInfo);
        }

        //生成交易信息
        TlTransactionInfo tlTransactionInfo = tlTransactionInfoService.buildTlTransactionInfo(amLoanMainInfo,
                TransBizConstant.TRANSCATION_REVERSAL_FLAG_0);
        transactionInfoList.add(tlTransactionInfo);

        //根据渠道信息判断是否需要记录营销记录
        if (CustomerConstant.YES_FLAG.equals(loanParamBean.getChannel().getMarketingRecordFlag())) {
            //创建营销信息
            TlMarketingRecord marketingRecord
                    = this.buildTlMarketingRecord(loanParamBean.getCustomer().getFirstLevel(), loanParamBean.getCustomer().getSecondLevel(), loanConfirmReq.getLoanAmount(), amLoanMainInfo.getLoanId(), loanConfirmReq.getSeqNo());
            if (null != marketingRecord) {
                extTlMarketingRecordMapper.insertSelective(marketingRecord);
            }
        }
        //更新优惠券状态
        if (TransBizConstant.WAIVE_TYPE_2.equals(amLoanMainInfo.getWaiveType())) {
            customerRightService.updateCustRight(amLoanMainInfo.getCustRightId(), amLoanMainInfo.getLoanId(), CustomerConstant.RIGHTS_STATUS_1, amLoanMainInfo.getCustomerId(), amLoanMainInfo.getTenantId());
        }
        //判断是否立即生成账单
        //交易入账日起息
        if (loanParamBean.getInterestTable().getStartDateFlag().equals(TransBizConstant.START_DATE_FLAG_1)) {
            logger.debug("获取立即抛账标志 ,1 交易入账日起息 ");
            //订单入库
            amLoanMainInfoMapper.insertSelective(amLoanMainInfo);
            //订单账户入库
            amLoanAccountInfoMapper.insertSelective(amLoanAccountInfo);
            //总账流水入库
            if (!CollectionUtils.isEmpty(glInterfaceInfoList)) {
                extTlGlInterfaceInfoMapper.batchInsertSelective(glInterfaceInfoList);
            }

            if (CollectionUtils.isNotEmpty(transactionInfoList)) {
                //交易信息入库
                extTlTransactionInfoMapper.batchInsert(transactionInfoList);
            }
            return this.buildRes(loanConfirmReq.getUserId(), amLoanMainInfo, null, amLoanAccountInfo.getAccountStatus());
        }

        logger.debug("构建还款计划");
        //生成还款计划入参
        LoanPlanParamBean loanPlanParamBean = repaymentPlanService.buildLoanPlanParamBean(amLoanMainInfo,
                businessDate, amLoanMainInfo.getLoanAmount(), amLoanMainInfo.getTotalTenor(), loanParamBean, loanParamBean.getFirstPaymentDate());
        //调用工具类生成还款计划
        List<AmRepaymentPlanInfo> amRepaymentPlanInfoList = repaymentPlanService.buildRepaymentList(loanPlanParamBean);
        logger.debug("新订单及订单账户信息");
        updateAmLoanInfo(amLoanMainInfo, amLoanAccountInfo, amRepaymentPlanInfoList, loanPlanParamBean, businessDate);
        updateGl(amLoanMainInfo, glInterfaceInfoList);

        List<AmInterestAccrualInfo> accuAcctList = new ArrayList<>();
        List<AmWaiveRepaymentPlanInfo> waiveRepaymentPlanInfoList = new ArrayList<>();
        //产品贴息生成贴息还款计划
        if (TransBizConstant.WAIVE_TYPE_1.equals(amLoanMainInfo.getWaiveType())) {
            waiveRepaymentPlanInfoList = repaymentPlanService.buildWaiveRepaymentListByProduct(amRepaymentPlanInfoList, loanPlanParamBean);
            waiveRepaymentPlanInfoList = waiveRepaymentPlanInfoList.stream().filter(plan -> plan.getInterestAmount().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
            CastWaiveAccountBean castWaiveAccountBean = accountService.castTxnWaiveAccount(amLoanMainInfo, amLoanAccountInfo, waiveRepaymentPlanInfoList, amRepaymentPlanInfoList, businessDate, false);
            if (null != castWaiveAccountBean) {
                accuAcctList.addAll(castWaiveAccountBean.getInterestAccrualInfoList());
            }
        }

        //权益贴息 促销活动贴息 生成贴息还款计划
        if (TransBizConstant.WAIVE_TYPE_2.equals(amLoanMainInfo.getWaiveType()) || TransBizConstant.WAIVE_TYPE_3.equals(amLoanMainInfo.getWaiveType())) {
            waiveRepaymentPlanInfoList = repaymentPlanService.buildWaiveRepaymentListByCustRightOrPromotion(amRepaymentPlanInfoList, loanPlanParamBean);
            waiveRepaymentPlanInfoList = waiveRepaymentPlanInfoList.stream().filter(plan -> plan.getInterestAmount().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
            CastWaiveAccountBean castWaiveAccountBean = accountService.castTxnWaiveAccount(amLoanMainInfo, amLoanAccountInfo, waiveRepaymentPlanInfoList, amRepaymentPlanInfoList, businessDate, false);
            if (null != castWaiveAccountBean) {
                accuAcctList.addAll(castWaiveAccountBean.getInterestAccrualInfoList());
            }
        }

        CastAccountBean castAccountBean = accountService.castTxnAccount(amLoanMainInfo, amLoanAccountInfo, amRepaymentPlanInfoList,
                businessDate, false);


        logger.debug("订单 还款计划  总账流水 支付流水 账户入库");
        //订单入库
        amLoanMainInfoMapper.insertSelective(amLoanMainInfo);
        //订单账户入库
        amLoanAccountInfoMapper.insertSelective(amLoanAccountInfo);
        //还款计划入库
        extAmRepaymentPlanInfoMapper.insertAmRepaymentPlanInfoList(amRepaymentPlanInfoList);
        //贴息还款计划入库
        if (CollectionUtils.isNotEmpty(waiveRepaymentPlanInfoList)) {
            extAmWaiveRepaymentPlanInfoMapper.insertAmWaiveRepaymentPlanInfoList(waiveRepaymentPlanInfoList);
        }
        //若抛账 则账户入库
        if (castAccountBean != null) {
            //本金 费用账户入库
            if (!CollectionUtils.isEmpty(castAccountBean.getAccountMainInfoList())) {
                extAmAccountMainInfoMapper.batchInsertAccount(castAccountBean.getAccountMainInfoList());
            }
            //利息累计入库
            if (!CollectionUtils.isEmpty(castAccountBean.getInterestAccrualInfoList())) {
                accuAcctList.addAll(castAccountBean.getInterestAccrualInfoList());
            }

            List<TlTransactionInfo> transactionInfos = castAccountBean.getTransactionInfoList();
            transactionInfoList.addAll(transactionInfos);

            glInterfaceInfoList.addAll(castAccountBean.getGlInterfaceInfoList());
        }


        //当日借当日还，借款时计提当天利息
        if (!CollectionUtils.isEmpty(accuAcctList)) {
            if (TransBizConstant.LOAN_DAY_PAY_FLAG_1.equals(prProductTable.getLoanDayPayFlag())) {
                PrOrganizationTable org = loanParamBean.getOrg();
                List<IntrAccuBean> intrAccuBeanList = this.calInterest(amLoanMainInfo, amLoanAccountInfo, accuAcctList, org);
                if (!CollectionUtils.isEmpty(intrAccuBeanList)) {
                    intrAccuBeanList.stream()
                            .map(IntrAccuBean::getTlGlInterfaceInfoList)
                            .filter(CollectionUtils::isNotEmpty)
                            .forEach(glInterfaceInfoList::addAll);

                    intrAccuBeanList.stream()
                            .map(IntrAccuBean::getTransactionInfoList)
                            .filter(CollectionUtils::isNotEmpty)
                            .forEach(transactionInfoList::addAll);

                    List<TlInterestAccrualLog> logList = intrAccuBeanList.stream()
                            .flatMap(log -> log.getTlInterestAccrualLogList().stream())
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());
                    extTlInterestAccrualLogMapper.batchInsert(logList);
                }
            }
            extAmInterestAccrualInfoMapper.batchInsertInterestAccrualInfo(accuAcctList);
        }

        //总账流水入库
        if (!CollectionUtils.isEmpty(glInterfaceInfoList)) {
            extTlGlInterfaceInfoMapper.batchInsertSelective(glInterfaceInfoList);
        }

        //交易信息入库
        if (!CollectionUtils.isEmpty(transactionInfoList)) {
            extTlTransactionInfoMapper.batchInsert(transactionInfoList);
        }

        //订单返回定义
        return this.buildRes(loanConfirmReq.getUserId(), amLoanMainInfo, amRepaymentPlanInfoList, amLoanAccountInfo.getAccountStatus());
    }

    /**
     * 更新gl
     *
     * @param amLoanMainInfo
     * @param glInterfaceInfoList
     */
    private void updateGl(AmLoanMainInfo amLoanMainInfo, List<TlGlInterfaceInfo> glInterfaceInfoList) {
        glInterfaceInfoList.forEach(tlGlInterfaceInfo -> {
                    tlGlInterfaceInfo.setAttributeReserve2(amLoanMainInfo.getTotalDays().toString());
                }
        );
    }

    /**
     * 计一天息
     *
     * @param loanMainInfo
     * @param loanAccountInfo
     * @param accuAcctList
     * @param org
     * @return
     * @throws TxnException
     */
    private List<IntrAccuBean> calInterest(AmLoanMainInfo loanMainInfo, AmLoanAccountInfo loanAccountInfo, List<AmInterestAccrualInfo> accuAcctList, PrOrganizationTable org) throws TxnException {
        List<IntrAccuBean> intrAccuBeanList = new ArrayList<>();
        Date bussinessDate = org.getNextProcessingDate();
        Date accruDay = DateUtils.addDay(org.getAccruThruDate(), 1);
        for (AmInterestAccrualInfo accuAcct : accuAcctList) {
            DealIntrBean dealIntrBean = new DealIntrBean();
            dealIntrBean.setLoanAcct(loanAccountInfo);
            dealIntrBean.setLoanMain(loanMainInfo);
            dealIntrBean.setAccuAcct(accuAcct);
            dealIntrBean.setBusinessDate(bussinessDate);
            dealIntrBean.setAccruDay(accruDay);
            IntrAccuBean intrAccuBean = interestCalculateService.calculateInterest(dealIntrBean);
            if (null != intrAccuBean) {
                intrAccuBeanList.add(intrAccuBean);
            }
        }
        return intrAccuBeanList;
    }

    /**
     * 到账日起息，到账成功后处理
     *
     * @param amLoanMainInfo
     * @param amLoanAccountInfo
     * @param businessDate
     * @return
     * @throws TxnException
     */
    @Override
    public AfterSucSaveBean afterLoanSuccess(AmLoanMainInfo amLoanMainInfo, AmLoanAccountInfo amLoanAccountInfo, Date businessDate) throws TxnException {
        AfterSucSaveBean afterSucSaveBean = new AfterSucSaveBean();

        String orgId = amLoanMainInfo.getOrganizationId();
        String channelId = amLoanMainInfo.getChannel();
        String tenantId = amLoanMainInfo.getTenantId();
        String custId = amLoanMainInfo.getCustomerId();
        PrInterestTable interest = interestTableService.findInterestByInterestId(amLoanMainInfo.getInterestTableId(), tenantId);

        //交易生效日起息 补一条五级分类变动
        if (interest.getStartDateFlag().equals(TransBizConstant.START_DATE_FLAG_0)) {
            return null;
        }

        PrProductTable prProductTable = productTableService.findProByProIdAndOrgId(amLoanMainInfo.getProductId(), amLoanMainInfo.getOrganizationId(), amLoanMainInfo.getTenantId());
        //计算账单日并更新客户信息
        Date firstPaymentDate = amLoanMainInfo.getFirstPaymentDate();
        String paymentDateType = prProductTable.getPaymentDateType();
        String statementDayType = prProductTable.getStatementDayType();
        String loanDurationUnit = prProductTable.getLoanDurationUnit();
        Integer loanDurationValue = prProductTable.getLoanDurationValue();
        Integer statemntInterval = prProductTable.getStatemntInterval();
        Integer paymentDateDd = amLoanMainInfo.getPaymentDateDd();
        Integer statementDay = amLoanMainInfo.getBillingCycle();

        PrChannelTable channel = channelTableService.getChannelTableByChannelIdAndStatus(TransBizConstant.YES_FLAG, channelId, tenantId);
        CmCustomerSecondLevel customer = customerService.getSecondByChannelAndCustomerIdAndTensnId(channelId, custId, tenantId, null);
        Integer paymentDd = customer.getPaymentDd();
        //还款日
        if (TransBizConstant.PAYMENT_DATE_TYPE_1.equals(paymentDateType)) {
            if (null == paymentDateDd) {
                //固定账单日
                if (TransBizConstant.IS_FIXED_BILLING.equals(channel.getIsFixedBilling())) {
                    if (null == paymentDd) {
                        //paymentDateDd = this.getPaymentDayByRule(orgId, prProductTable.getProductId(), businessDate, tenantId);
                        //固定账单日  更新客户上的还款日
                        customerService.editPaymentDd(custId, orgId, channelId, paymentDateDd, tenantId);
                    } /*else {
                        paymentDateDd = paymentDd;
                    }
                } else {*/
                }
                paymentDateDd = this.getPaymentDayByRule(orgId, prProductTable.getProductId(), businessDate, tenantId);

            }
            firstPaymentDate = repaymentPlanService.computeFirstPaymentDate(businessDate, paymentDateDd, statemntInterval); //首次还款日

        } else if (TransBizConstant.PAYMENT_DATE_TYPE_3.equals(paymentDateType)) {
            if (TransBizConstant.LOAN_DURATION_MONTH.equals(loanDurationUnit)) {//月
                firstPaymentDate = DateUtils.getDateByMonth(businessDate, loanDurationValue);
            } else if (TransBizConstant.LOAN_DURATION_WEEK.equals(loanDurationUnit)) {//周
                firstPaymentDate = DateUtils.getDate(businessDate, loanDurationValue * 7);
            } else {//天
                firstPaymentDate = DateUtils.getDate(businessDate, loanDurationValue);
            }
            paymentDateDd = Integer.parseInt(DateUtils.getDay(firstPaymentDate));
        }


        //账单日
        if (null == statementDay) {
            //固定账单日，如果二级档有取二级档
            if (TransBizConstant.IS_FIXED_BILLING.equals(channel.getIsFixedBilling())) {
                if (null == customer.getStatementDd()) {
                    if (TransBizConstant.STATEMENT_DATE_TYPE_3.equals(statementDayType)) {
                        //否则通过规则获取
                        statementDay = this.getStatementDayByRule(channel.getOrganizationId(), prProductTable.getProductId(), businessDate, tenantId);
                    } else if (TransBizConstant.STATEMENT_DATE_TYPE_1.equals(statementDayType)) {
                        //或者获取还款日
                        statementDay = paymentDateDd;
                    }
                    customerService.editByUserIdAndOrgIdAndChannel(custId, orgId, channelId, statementDay, tenantId);
                } else {
                    //statementDay = customer.getStatementDd();
                    statementDay = this.getStatementDayByRule(channel.getOrganizationId(), prProductTable.getProductId(), businessDate, tenantId);
                }
            } else {
                //非固定账单日通过规则获取
                if (TransBizConstant.STATEMENT_DATE_TYPE_3.equals(statementDayType)) {
                    //否则通过规则获取
                    statementDay = this.getStatementDayByRule(channel.getOrganizationId(), prProductTable.getProductId(), businessDate, tenantId);
                } else if (TransBizConstant.STATEMENT_DATE_TYPE_1.equals(statementDayType)) {
                    //或者获取还款日
                    statementDay = paymentDateDd;
                }
            }
        }
        //或者账单日规则需要重新计算首期还款日
        if (TransBizConstant.STATEMENT_DATE_TYPE_3.equals(statementDayType)) {
            firstPaymentDate = this.getFirstPaymentDate(paymentDateDd, statementDay, businessDate);
        }


        amLoanMainInfo.setBillingCycle(statementDay);
        amLoanMainInfo.setPaymentDateDd(paymentDateDd);

        logger.debug("构建还款计划");
        //生成还款计划入参
        LoanPlanParamBean loanPlanParamBean = repaymentPlanService.buildLoanPlanParamBean(amLoanMainInfo,
                businessDate, amLoanMainInfo.getLoanAmount(), amLoanMainInfo.getTotalTenor(), null, firstPaymentDate);
        loanPlanParamBean.setInterestTable(interest);
        loanPlanParamBean.setPrProductTable(prProductTable);
        loanPlanParamBean.setMinIntervalDays(prProductTable.getStatemntInterval());
        //调用工具类生成还款计划
        List<AmRepaymentPlanInfo> amRepaymentPlanInfoList = repaymentPlanService.buildRepaymentList(loanPlanParamBean);
        logger.debug("新订单及订单账户信息");
        updateAmLoanInfo(amLoanMainInfo, amLoanAccountInfo, amRepaymentPlanInfoList, loanPlanParamBean, businessDate);

        //生成贴息还款计划
        List<AmInterestAccrualInfo> accuAcctList = new ArrayList<>();
        //产品贴息生成贴息还款计划
        List<AmWaiveRepaymentPlanInfo> waiveRepaymentPlanInfoList = new ArrayList<>();
        if (TransBizConstant.WAIVE_TYPE_1.equals(amLoanMainInfo.getWaiveType())) {
            waiveRepaymentPlanInfoList = repaymentPlanService.buildWaiveRepaymentListByProduct(amRepaymentPlanInfoList, loanPlanParamBean);
            CastWaiveAccountBean castWaiveAccountBean = accountService.castTxnWaiveAccount(amLoanMainInfo, amLoanAccountInfo, waiveRepaymentPlanInfoList, amRepaymentPlanInfoList, businessDate, false);
            if (null != castWaiveAccountBean) {
                accuAcctList.addAll(castWaiveAccountBean.getInterestAccrualInfoList());
            }
        }

        //权益贴息 促销活动贴息 生成贴息还款计划
        if (TransBizConstant.WAIVE_TYPE_2.equals(amLoanMainInfo.getWaiveType()) || TransBizConstant.WAIVE_TYPE_3.equals(amLoanMainInfo.getWaiveType())) {
            waiveRepaymentPlanInfoList = repaymentPlanService.buildWaiveRepaymentListByCustRightOrPromotion(amRepaymentPlanInfoList, loanPlanParamBean);
            CastWaiveAccountBean castWaiveAccountBean = accountService.castTxnWaiveAccount(amLoanMainInfo, amLoanAccountInfo, waiveRepaymentPlanInfoList, amRepaymentPlanInfoList, businessDate, false);
            if (null != castWaiveAccountBean) {
                accuAcctList.addAll(castWaiveAccountBean.getInterestAccrualInfoList());
            }
        }


        CastAccountBean castAccountBean = accountService.castTxnAccount(amLoanMainInfo, amLoanAccountInfo, amRepaymentPlanInfoList,
                businessDate, false);

        logger.debug("订单更新 还款计划  总账流水 支付流水 账户入库");
        afterSucSaveBean.setUpdateLoanMainInfo(amLoanMainInfo);
        afterSucSaveBean.setUpdateLoanAccountInfo(amLoanAccountInfo);
        afterSucSaveBean.setSavePlanList(amRepaymentPlanInfoList);
        if (CollectionUtils.isNotEmpty(waiveRepaymentPlanInfoList)) {
            afterSucSaveBean.setSaveWaivePlanList(waiveRepaymentPlanInfoList.stream().filter(plan -> plan.getInterestAmount().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList()));
        }
        //若抛账 则账户入库
        if (null == castAccountBean) {
            throw new TxnException(TxnRespCode.BIZ_ERROR.getCode(), TxnRespCode.BIZ_ERROR.getMsg());
        }

        //本金 费用账户入库
        afterSucSaveBean.setSaveAcctList(castAccountBean.getAccountMainInfoList());
        //利息累计
        accuAcctList.addAll(castAccountBean.getInterestAccrualInfoList());

        //利息累计入库
        if (TransBizConstant.LOAN_DAY_PAY_FLAG_1.equals(prProductTable.getLoanDayPayFlag())) {
            PrOrganizationTable org = organizationTableService.findByOrId(orgId, tenantId);
            List<IntrAccuBean> intrAccuBeanList = this.calInterest(amLoanMainInfo, amLoanAccountInfo, accuAcctList, org);
            if (!CollectionUtils.isEmpty(intrAccuBeanList)) {
                intrAccuBeanList.stream()
                        .map(IntrAccuBean::getTlGlInterfaceInfoList)
                        .filter(CollectionUtils::isNotEmpty)
                        .forEach(castAccountBean.getGlInterfaceInfoList()::addAll);

                intrAccuBeanList.stream()
                        .map(IntrAccuBean::getTransactionInfoList)
                        .filter(CollectionUtils::isNotEmpty)
                        .forEach(castAccountBean.getTransactionInfoList()::addAll);

                List<TlInterestAccrualLog> logList =
                        intrAccuBeanList.stream()
                                .flatMap(log -> log.getTlInterestAccrualLogList().stream())
                                .filter(Objects::nonNull)
                                .collect(Collectors.toList());
                afterSucSaveBean.setSaveIntrAccrualLogList(logList);
            }
        }
        afterSucSaveBean.setSaveAccuAcctList(accuAcctList);

        //总账流水入库
        afterSucSaveBean.setSaveGlList(castAccountBean.getGlInterfaceInfoList());

        //交易信息入库
        afterSucSaveBean.setSaveTransList(castAccountBean.getTransactionInfoList());

        return afterSucSaveBean;
    }

    @Override
    public void checkLoanStatus(AmLoanAccountInfo amLoanAccountInfo) throws TxnException {
        if (TransBizConstant.LOAN_STATUS_0.equals(amLoanAccountInfo.getAccountStatus())) {
            logger.error(TxnRespCode.TRANSACTION_PROCESSING.getMsg());
            throw new TxnBizException(TxnRespCode.TRANSACTION_PROCESSING.getCode(),
                    TxnRespCode.TRANSACTION_PROCESSING.getMsg());
        }
    }


    /**
     * 根据账单日获取首期还款日
     *
     * @param paymentDay
     * @param statementDay
     * @param loanDate
     * @return
     */
    @Override
    public Date getFirstPaymentDate(int paymentDay, int statementDay, Date loanDate) {
        //获取该月账单日
        Date statementDate = DateUtils.getThisMonthDate(loanDate, statementDay);
        if (statementDate.compareTo(loanDate) <= 0) {
            statementDate = DateUtils.addMonth(statementDate, 1);
        }

        Date firstPaymentDate = DateUtils.getThisMonthDate(statementDate, paymentDay);
        if (firstPaymentDate.compareTo(statementDate) < 0) {
            firstPaymentDate = DateUtils.addMonth(firstPaymentDate, 1);

        }
        return firstPaymentDate;
    }

    /**
     * 借款记录查询
     * @param req
     * @return
     */
    @Override
    public LoanListQueryRes loanListQuery(LoanListQueryReq req) throws TxnBizException {
        LoanListQueryRes res = new LoanListQueryRes();

        List<String> productIds = null;
        if (StringUtils.isNotBlank(req.getBizType())) {
            BizTypeEnum bizTypeEnum = BizTypeEnum.getByCode(req.getBizType());
            productIds = BizTypeProducts.getByBizType(bizTypeEnum);
        }

        String channel = req.getChannel();
        String tenantId = req.getTenantId();
        CustomerSecondLevelRes customer = customerService.getByUserIdAndChannel(req.getUserId(),channel, tenantId);
        String customerId = customer.getCustomerId();
        List<TlDisbursementLog> disbursementLogs = new ArrayList<>();
        // 1.在途、2.完结
        if (1 ==  req.getQueryType()) {
            // 查询正在支出中的借据
            disbursementLogs.addAll(extTlDisbursementLogMapper.selectUnderDisbursement(customerId, channel, tenantId,
                    Arrays.asList(TransBizConstant.DISBURSEMENT_LOG_SUM_STATUS_D, TransBizConstant.DISBURSEMENT_LOG_SUM_STATUS_O), productIds));
        }
        List<String> accountStatus = new ArrayList<>(Arrays.asList(TransBizConstant.ACCOUNT_STATUS_0, TransBizConstant.ACCOUNT_STATUS_1, TransBizConstant.ACCOUNT_STATUS_2,
                TransBizConstant.ACCOUNT_STATUS_7, TransBizConstant.ACCOUNT_STATUS_8, TransBizConstant.ACCOUNT_STATUS_9));
        // 查询贷款历史记录
        List<AmLoanAccountInfo> amLoanAccountInfoList = extAmLoanAccountInfoMapper.selectByCustProductsAndChannelAndStatus(customerId, channel, tenantId, accountStatus, productIds);
        List<AmLoanMainInfo> loanMainInfoList = extAmLoanMainInfoMapper.selectByCusIdtProductIdsAndTenantId(customerId, tenantId, productIds);
        List<AmRepaymentPlanInfo> planInfoRes = extAmRepaymentPlanInfoMapper.queryPlanInfo(tenantId, channel, customerId, null, productIds);
        List<LoanHistoryVo> loanHistories = new ArrayList<>();
        amLoanAccountInfoList.forEach(accountInfo -> {
            LoanHistoryVo vo = new LoanHistoryVo();
            vo.setLoanId(accountInfo.getLoanId());
            AmLoanMainInfo amLoanMainInfo = loanMainInfoList.stream().filter(loan -> loan.getLoanId().equalsIgnoreCase(accountInfo.getLoanId())).findFirst().get();
            vo.setLoanAmount(amLoanMainInfo.getLoanAmount());
            vo.setLoanDate(amLoanMainInfo.getTxnTime());
            vo.setLoanReqSeq(amLoanMainInfo.getSerialNumber());
            Optional<TlDisbursementLog> logOptional = disbursementLogs.stream()
                    .filter(dis -> dis.getLoanId().equalsIgnoreCase(accountInfo.getLoanId()))
                    .filter(dis -> Arrays.asList(TransBizConstant.DISBURSEMENT_LOG_SUM_STATUS_D, TransBizConstant.DISBURSEMENT_LOG_SUM_STATUS_O).contains(dis.getSumStatus()))
                    .findFirst();
            if (logOptional.isPresent()) {
                vo.setLoanStatus("0");
            } else {
                // 设置 借款状态 0.借款处理中、1.使用中、2.已逾期、3.已结清、4.失败、5.取消
                vo.setLoanStatus(changeLoanStatus(accountInfo.getAccountStatus()));
            }
            AmRepaymentPlanInfo maxPlan = planInfoRes.stream()
                    .filter(plan -> plan.getLoanId().equalsIgnoreCase(accountInfo.getLoanId()))
                    .sorted(
                            Comparator.comparing(AmRepaymentPlanInfo::getBillingTenor, Comparator.reverseOrder())
                                    .thenComparing(AmRepaymentPlanInfo::getCreateTime, Comparator.reverseOrder())
                    ).collect(Collectors.toList()).get(0);
            // 借款结束日期
            vo.setLoanEndDate(maxPlan.getPaymentDueDate());
            if (Objects.nonNull(maxPlan.getPayoffDate())
                    && Arrays.asList(TransBizConstant.LOAN_PLAN_STATUS_7, TransBizConstant.LOAN_PLAN_STATUS_8).contains(maxPlan.getPlanStatus())) {
                vo.setLoanEndDate(maxPlan.getPayoffDate());
            }

            loanHistories.add(0, vo);
        });
        List<LoanHistoryVo> collect = loanHistories.stream().sorted(Comparator.comparing(LoanHistoryVo::getLoanDate).reversed()).collect(Collectors.toList());
        res.setLoanHistories(collect);
        return res;
    }

    /**
     * 转换借款状态
     * 0.借款处理中、1.使用中、2.已逾期、3.已结清、4.失败、5.取消
     * @param accountStatus
     * @return
     */
    private String changeLoanStatus(String accountStatus) {
        switch (accountStatus){
            case TransBizConstant.ACCOUNT_STATUS_2 :
                return  "2";
            case TransBizConstant.ACCOUNT_STATUS_7 :
            case TransBizConstant.ACCOUNT_STATUS_8 :
                return  "3";
            case TransBizConstant.ACCOUNT_STATUS_9 :
                return  "4";
            default :
                return "1";
        }
    }

    @Override
    public LoanConfirmRes generatingOrderByLoanStaging(LoanParamBean loanParamBean, LoanConfirmReq loanConfirmReq) throws TxnException {
        //业务日期
        Date businessDate = loanParamBean.getOrg().getNextProcessingDate();
        logger.debug("构建贷款订单");
        AmLoanMainInfo amLoanMainInfo = loanMainInfoService.buildLoanMainInfo(loanParamBean, loanConfirmReq, businessDate);

        logger.debug("构建贷款账户信息");
        AmLoanAccountInfo amLoanAccountInfo = loanAccountMainInfoService.buildAmLoanAccountInfo(amLoanMainInfo);

        logger.debug("构建总账流水");
        List<TlGlInterfaceInfo> glInterfaceInfoList = new ArrayList<>();
        List<TlTransactionInfo> transactionInfoList = new ArrayList<>();
        TlGlInterfaceInfo tlGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInfo(amLoanMainInfo,
                amLoanAccountInfo, loanParamBean.getProduct().getChineseName(), businessDate, TransBizConstant.LIABILITY_FLAG_00);
        if (null != tlGlInterfaceInfo) {
            glInterfaceInfoList.add(tlGlInterfaceInfo);
        }

        //是否立即抛账  利率表 起息日 为 0 立刻出账
        logger.info("获取立即抛账标志 ,0 立刻出账");
        //判断是否立即生成账单
        if (loanParamBean.getInterestTable().getStartDateFlag().equals(TransBizConstant.START_DATE_FLAG_1)) {
            //订单入库
            amLoanMainInfoMapper.insertSelective(amLoanMainInfo);
            //订单账户入库
            amLoanAccountInfoMapper.insertSelective(amLoanAccountInfo);
            //总账流水入库
            if (!CollectionUtils.isEmpty(glInterfaceInfoList)) {
                extTlGlInterfaceInfoMapper.batchInsertSelective(glInterfaceInfoList);
            }

            //交易信息入库
            extTlTransactionInfoMapper.batchInsert(transactionInfoList);
            LoanConfirmRes loanConfirmRes = this.buildRes(loanConfirmReq.getUserId(), amLoanMainInfo, null, amLoanAccountInfo.getAccountStatus());
            return loanConfirmRes;
        }

        logger.debug("构建还款计划");
        //生成还款计划入参
        LoanPlanParamBean loanPlanParamBean = repaymentPlanService.buildLoanPlanParamBean(amLoanMainInfo,
                businessDate, amLoanMainInfo.getLoanAmount(), amLoanMainInfo.getTotalTenor(),
                loanParamBean, loanParamBean.getFirstPaymentDate());
        //调用工具类生成还款计划
        List<AmRepaymentPlanInfo> amRepaymentPlanInfoList = repaymentPlanService.buildRepaymentList(loanPlanParamBean);

        logger.debug("新订单及订单账户信息");
        updateAmLoanInfo(amLoanMainInfo, amLoanAccountInfo, amRepaymentPlanInfoList, loanPlanParamBean, businessDate);

        CastAccountBean castAccountBean = accountService.castTxnAccount(amLoanMainInfo, amLoanAccountInfo, amRepaymentPlanInfoList,
                businessDate, false);

        logger.debug("订单 还款计划  总账流水 支付流水 账户入库");
        //订单入库
        amLoanMainInfoMapper.insertSelective(amLoanMainInfo);
        //订单账户入库
        amLoanAccountInfoMapper.insertSelective(amLoanAccountInfo);
        //还款计划入库
        extAmRepaymentPlanInfoMapper.insertAmRepaymentPlanInfoList(amRepaymentPlanInfoList);
        //若抛账 则账户入库
        if (castAccountBean != null) {
            //本金 费用账户入库
            if (!CollectionUtils.isEmpty(castAccountBean.getAccountMainInfoList())) {
                extAmAccountMainInfoMapper.batchInsertAccount(castAccountBean.getAccountMainInfoList());
            }
            //利息累计入库
            if (!CollectionUtils.isEmpty(castAccountBean.getInterestAccrualInfoList())) {
                extAmInterestAccrualInfoMapper.batchInsertInterestAccrualInfo(castAccountBean.getInterestAccrualInfoList());
            }

            List<TlTransactionInfo> transactionInfos = castAccountBean.getTransactionInfoList();
            transactionInfoList.addAll(transactionInfos);

            glInterfaceInfoList.addAll(castAccountBean.getGlInterfaceInfoList());
        }

        //总账流水入库
        if (!CollectionUtils.isEmpty(glInterfaceInfoList)) {
            extTlGlInterfaceInfoMapper.batchInsertSelective(glInterfaceInfoList);
        }

        //交易信息入库
        if (!CollectionUtils.isEmpty(transactionInfoList)) {
            extTlTransactionInfoMapper.batchInsert(transactionInfoList);
        }

        //订单返回定义
        LoanConfirmRes loanConfirmRes = this.buildRes(loanConfirmReq.getUserId(), amLoanMainInfo, amRepaymentPlanInfoList, amLoanAccountInfo.getAccountStatus());
        return loanConfirmRes;
    }

    @Override
    public LoanConfirmRes getLoanInfoAndPaymentPlanList(LoanReq loanReq, LoanParamBean loanParamBean) throws TxnException {

        //还款计划生成入参生成
        logger.info("还款计划工具类入参bean赋值");
        LoanPlanParamBean loanPlanParamBean = repaymentPlanService.buildTrailLoanPlanParamBean(loanReq, loanParamBean);
        //构建还款计划
        List<AmRepaymentPlanInfo> amRepaymentPlanInfoList = repaymentPlanService.buildRepaymentList(loanPlanParamBean);

        //试算返回构建
        LoanConfirmRes loanConfirmRes = new LoanConfirmRes();
        loanConfirmRes.setFirstPaymentDueDate(amRepaymentPlanInfoList.get(0).getPaymentDueDate());//首期还款日
        loanConfirmRes.setLastPaymentDueDate(amRepaymentPlanInfoList.get(amRepaymentPlanInfoList.size() - 1).getPaymentDueDate()); //最后还款日

        loanConfirmRes.setDayRate(loanPlanParamBean.getDailyRate().stripTrailingZeros());//日利率
        loanConfirmRes.setYearRate(loanPlanParamBean.getYearRate().stripTrailingZeros());//年利率
        //获取每期利息金额
        //利息总金额
        loanConfirmRes.setTotalInterestAmount(amRepaymentPlanInfoList.parallelStream().collect(CollectorsUtils.summingBigDecimal(AmRepaymentPlanInfo::getInterestAmount)));

        //获取每期费用金额
        //费用总金额
        loanConfirmRes.setTotalFeeAmount(amRepaymentPlanInfoList.parallelStream().collect(CollectorsUtils.summingBigDecimal(AmRepaymentPlanInfo::getFeeAmount)));

        //获取总金额金额
        loanConfirmRes.setTotalPaymentAmount(amRepaymentPlanInfoList.parallelStream().collect(CollectorsUtils.summingBigDecimal(AmRepaymentPlanInfo::getTotalAmount)));

        //构建贷款返回信息
        loanConfirmRes.setUserId(loanReq.getUserId());//用户ID
        loanConfirmRes.setLoanAmount(loanReq.getLoanAmount());//贷款金额
        loanConfirmRes.setTenor(loanReq.getTenor());//期数
        //若利随本清重新赋值订单还款日
        if (TransBizConstant.PRIN_CHARGE_OPTION_INTPAY.equals(loanPlanParamBean.getAmortMethod().getChargeOption())) {
            loanConfirmRes.setPaymentDueDay(Integer.parseInt(DateUtils.getDay(amRepaymentPlanInfoList.get(0).getPaymentDueDate())));
        } else {
            loanConfirmRes.setPaymentDueDay(loanParamBean.getPaymentDay());//还款日
        }

        BeanMapping.Converter<AmRepaymentPlanInfo, RepaymentPlanRes> converter = (plan, res) -> res.setExemptAmount(plan.getWaivedAmount());
        List<RepaymentPlanRes> repaymentPlanResList = BeanMapping.copyList(amRepaymentPlanInfoList, RepaymentPlanRes.class, converter);

        loanConfirmRes.setPaymentPlanList(repaymentPlanResList);
        loanConfirmRes.setCustRightId(loanReq.getCustRightId());
        if (null != loanParamBean.getRightInfo()) {
            loanConfirmRes.setRightsName(loanParamBean.getRightInfo().getRightsName());
        }
        BigDecimal totalExemptAmount = repaymentPlanResList.stream().map(RepaymentPlanRes::getExemptAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        loanConfirmRes.setTotalExemptAmount(totalExemptAmount);

        if (null != loanPlanParamBean.getPrPromotionInfo()) {
            loanConfirmRes.setPromotionId(loanPlanParamBean.getPrPromotionInfo().getPromotionId());
            loanConfirmRes.setPromotionDesc(loanPlanParamBean.getPrPromotionInfo().getPromotionDesc());
        }

        return loanConfirmRes;
    }


    @Override
    public BigDecimal getPaidAmountByLoanIdAndStatusAndType(String loanId, String[] type, String cusId, String tenantId) {
        return extAmAccountMainInfoMapper.selectRePayAmountAmoByCondition(loanId, type, cusId, tenantId);
    }

    @Override
    public List<LoanRecordRes> getLoanMainByCondition(String channel, String customerId, String tenantId) throws TxnBizException {
        List<AmLoanMainInfo> amLoanMainInfoList = extAmLoanMainInfoMapper.selectLoanMainByCondition(channel, customerId, tenantId);
        List<AmLoanAccountInfo> remainPrincipalAllList = extAmLoanAccountInfoMapper.selectRemainPrincipalAllByLoanId(channel, customerId, tenantId);
        Map<String, AmLoanAccountInfo> map =
                remainPrincipalAllList.stream().collect(Collectors.toMap(AmLoanAccountInfo::getLoanId,
                        amLoanAccountInfo -> amLoanAccountInfo));
        List<LoanRecordRes> loanRecordResList = new ArrayList<>();
        for (AmLoanMainInfo amLoanMainInfo : amLoanMainInfoList
        ) {
            LoanRecordRes loanRecordRes = new LoanRecordRes();
            loanRecordRes.setLoanId(amLoanMainInfo.getLoanId());//贷款订单号
            loanRecordRes.setAmortMethodTableId(amLoanMainInfo.getAmortMethodTableId());//还款方式
            loanRecordRes.setProductId(amLoanMainInfo.getProductId());//产品编号
            loanRecordRes.setLoanTxnDate(amLoanMainInfo.getTxnTime());//交易日期;
            loanRecordRes.setLoanLendingDate(amLoanMainInfo.getPostingDate());//放款日期
            loanRecordRes.setLoanAmount(amLoanMainInfo.getLoanAmount());//贷款金额
            loanRecordRes.setLoanTenor(amLoanMainInfo.getTotalTenor());//总期数
            loanRecordRes.setLoanUse(amLoanMainInfo.getLoanUse());//贷款用途
            loanRecordRes.setPaidPrincipalAmount(amLoanMainInfo.getLoanAmount().subtract(map.get(amLoanMainInfo.getLoanId()).getRemainPrincipal()));//已还本金
            loanRecordRes.setAccountStatus(map.get(amLoanMainInfo.getLoanId()).getAccountStatus());//订单状态
            loanRecordRes.setPaymentDateDd(amLoanMainInfo.getPaymentDateDd());//还款日
            loanRecordRes.setCompelCollectionFlag(map.get(amLoanMainInfo.getLoanId()).getCompelCollectionFlag());
            //根据产品ID查询产品表的贷款期数单位
            PrProductTable productTable = productTableService.findProByProIdAndOrgId(amLoanMainInfo.getProductId(),
                    amLoanMainInfo.getOrganizationId(), amLoanMainInfo.getTenantId());
            loanRecordRes.setLoanDayPayFlag(productTable.getLoanDayPayFlag());

            loanRecordResList.add(loanRecordRes);
        }
        return loanRecordResList;
    }

    @Override
    public DisbursementLogRes getDisbursementByCondition(String loanId, String customerId, String tenantId) throws TxnBizException {
        TlDisbursementLog tlDisbursementLog = extTlDisbursementLogMapper.selectDisbursementByCondition(loanId,
                customerId, tenantId);
        if (tlDisbursementLog == null) {
            logger.error(TxnRespCode.NO_DATA.getUserTips());
            throw new TxnBizException(TxnRespCode.NO_DATA.getCode(), TxnRespCode.NO_DATA.getUserTips());
        }
        return BeanMapping.copy(tlDisbursementLog, DisbursementLogRes.class);
    }

    @Override
    public List<RepaymentPlanInfoRes> getRepaymentPlanListByLoanId(String loanId, String customerId, String tenantId) {
        String[] status = {TransBizConstant.LOAN_PLAN_STATUS_0, TransBizConstant.LOAN_PLAN_STATUS_1, TransBizConstant.LOAN_PLAN_STATUS_2, TransBizConstant.LOAN_PLAN_STATUS_7, TransBizConstant.LOAN_PLAN_STATUS_8};
        logger.debug("获取还款计划列表");
        List<AmRepaymentPlanInfo> repaymentPlanInfosList = extAmRepaymentPlanInfoMapper.selectRepaymentPlanInfoListByLoanIdAndStatus(loanId, status, customerId, tenantId);
        return BeanMapping.copyList(repaymentPlanInfosList, RepaymentPlanInfoRes.class);
    }


    @Override
    public BigDecimal getAmountByAccountMain(String loanId, Integer tenor, String type, String customerId,
                                             String tenantId) {
        return extAmAccountMainInfoMapper.selectPostingAmountByCondition(loanId, tenor, type, customerId, tenantId);
    }

    /**
     * 更新订单信息
     *
     * @param amLoanMainInfo          贷款信息
     * @param loanAccountInfo         贷款账户信息
     * @param amRepaymentPlanInfoList 还款计划列表
     * @param loanPlanParamBean       还款计划生成入参
     */
    private void updateAmLoanInfo(AmLoanMainInfo amLoanMainInfo, AmLoanAccountInfo loanAccountInfo,
                                  List<AmRepaymentPlanInfo> amRepaymentPlanInfoList, LoanPlanParamBean loanPlanParamBean, Date bussinessDate) {
        amLoanMainInfo.setFirstPaymentDate(amRepaymentPlanInfoList.get(0).getPaymentDueDate());//首期还款日
        amLoanMainInfo.setLastPaymentDate(amRepaymentPlanInfoList.get(amRepaymentPlanInfoList.size() - 1).getPaymentDueDate()); //最后还款日
        //下次还款日
        Date nextPaymentDay = amRepaymentPlanInfoList.size() == 1 ? amLoanMainInfo.getFirstPaymentDate()
                : amRepaymentPlanInfoList.get(1).getPaymentDueDate();
        loanAccountInfo.setNextPaymentDate(nextPaymentDay);//设置下次还款日期
        //若利随本清重新赋值订单还款日
        if (TransBizConstant.PRIN_CHARGE_OPTION_INTPAY.equals(loanPlanParamBean.getAmortMethod().getChargeOption())) {
            amLoanMainInfo.setBillingCycle(Integer.parseInt(DateUtils.getDay(nextPaymentDay)));
        }
        int totalDays = DateUtils.getDaysBetween(amLoanMainInfo.getPostingDate(), amLoanMainInfo.getLastPaymentDate());
        amLoanMainInfo.setTotalDays(totalDays);
        amLoanMainInfo.setTotalTenor(amRepaymentPlanInfoList.size());
        amLoanMainInfo.setPostingDate(bussinessDate);
        amLoanMainInfo.setOrigDailyRate(loanPlanParamBean.getDailyRate());//折扣前利率
        amLoanMainInfo.setActualDailyRate(loanPlanParamBean.getDailyRate());//日利率
        amLoanMainInfo.setInterestRate(loanPlanParamBean.getYearRate());//年利率
        if (null != loanPlanParamBean.getRightInfo() && CustomerConstant.RIGHTS_TYPE_02.equals(loanPlanParamBean.getRightInfo().getRightsType())) {
            amLoanMainInfo.setActualDailyRate(amLoanMainInfo.getOrigDailyRate().multiply(loanPlanParamBean.getRightInfo().getDiscountRate()).setScale(CommonContants.BIGDECIMAL_SCALE_7, BigDecimal.ROUND_HALF_UP));
            amLoanMainInfo.setDiscountRate(loanPlanParamBean.getRightInfo().getDiscountRate());
        }
        //促销活动
        if (loanPlanParamBean.getPrPromotionInfo() != null) {
            PrPromotionInfo prPromotionInfo = loanPlanParamBean.getPrPromotionInfo();
            String rateFlag = prPromotionInfo.getRateFlag();
            //1 = 利率打折
            if (TransBizConstant.PROMOTION_RATE_FLAG_1.equals(rateFlag)) {
                amLoanMainInfo.setActualDailyRate(amLoanMainInfo.getOrigDailyRate().multiply(prPromotionInfo.getRateDiscountPercentage()).setScale(CommonContants.BIGDECIMAL_SCALE_7, BigDecimal.ROUND_HALF_UP));
                amLoanMainInfo.setDiscountRate(prPromotionInfo.getRateDiscountPercentage());
            }
            //2 = 固定利率
            else if (TransBizConstant.PROMOTION_RATE_FLAG_2.equals(rateFlag)) {
                amLoanMainInfo.setOriginalInterestTableId(amLoanMainInfo.getInterestTableId());
                amLoanMainInfo.setInterestTableId(prPromotionInfo.getInterestTableId());
            }
        }
        BigDecimal afterDiscountIntr = amRepaymentPlanInfoList.stream().map(AmRepaymentPlanInfo::getInterestAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal discountIntr = amRepaymentPlanInfoList.stream().map(AmRepaymentPlanInfo::getWaivedAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        amLoanMainInfo.setInterestBeforeDiscount(afterDiscountIntr.add(discountIntr));
        amLoanMainInfo.setInterestDiscount(discountIntr);
        amLoanMainInfo.setInterestStartDate(amRepaymentPlanInfoList.get(0).getIntrStartDate());
    }

    /**
     * 构建返回结果
     *
     * @param userId
     * @param amLoanMainInfo
     * @param planInfoList
     * @return
     */
    @Override
    public LoanConfirmRes buildRes(String userId, AmLoanMainInfo amLoanMainInfo, List<AmRepaymentPlanInfo> planInfoList, String loanStatus) throws TxnBizException {
        LoanConfirmRes loanConfirmRes = BeanMapping.copy(amLoanMainInfo, LoanConfirmRes.class);
        //构建贷款返回信息
        loanConfirmRes.setUserId(userId);
        loanConfirmRes.setLoanId(amLoanMainInfo.getLoanId());
        loanConfirmRes.setTenor(amLoanMainInfo.getTotalTenor());
        loanConfirmRes.setDayRate(amLoanMainInfo.getActualDailyRate());
        loanConfirmRes.setYearRate(amLoanMainInfo.getInterestRate());
        loanConfirmRes.setLoanAmount(amLoanMainInfo.getLoanAmount());
        loanConfirmRes.setLoanStatus(loanStatus);
        if (loanStatus.equals(TransBizConstant.LOAN_STATUS_0)) {
            return loanConfirmRes;
        }

        loanConfirmRes.setPaymentDueDay(amLoanMainInfo.getPaymentDateDd());
        loanConfirmRes.setFirstPaymentDueDate(amLoanMainInfo.getFirstPaymentDate());
        loanConfirmRes.setLastPaymentDueDate(amLoanMainInfo.getLastPaymentDate());

        //获取每期利息金额
        loanConfirmRes.setTotalInterestAmount(planInfoList.parallelStream().collect(CollectorsUtils.summingBigDecimal(AmRepaymentPlanInfo::getInterestAmount)));

        //获取每期费用金额
        loanConfirmRes.setTotalFeeAmount(planInfoList.parallelStream().collect(CollectorsUtils.summingBigDecimal(AmRepaymentPlanInfo::getFeeAmount)));

        //获取总金额金额
        loanConfirmRes.setTotalPaymentAmount(planInfoList.parallelStream().collect(CollectorsUtils.summingBigDecimal(AmRepaymentPlanInfo::getTotalAmount)));

        BeanMapping.Converter<AmRepaymentPlanInfo, RepaymentPlanRes> converter = (plan, res) -> res.setExemptAmount(plan.getWaivedAmount());
        List<RepaymentPlanRes> repaymentPlanResList = BeanMapping.copyList(planInfoList, RepaymentPlanRes.class, converter);
        loanConfirmRes.setPaymentPlanList(repaymentPlanResList);
        loanConfirmRes.setCustRightId(amLoanMainInfo.getCustRightId());
        if (TransBizConstant.WAIVE_TYPE_2.equals(amLoanMainInfo.getWaiveType())) {
            CmCustomerRightInfo rightInfo = customerRightService.getRightInfoById(amLoanMainInfo.getCustRightId(), amLoanMainInfo.getCustomerId(), amLoanMainInfo.getTenantId());
            loanConfirmRes.setRightsName(rightInfo.getRightsName());
        }
        if (TransBizConstant.WAIVE_TYPE_3.equals(amLoanMainInfo.getWaiveType())) {
            PrPromotionInfo prPromotionInfo = prPromotionInfoService.findByPromotionIdAndTenId(amLoanMainInfo.getPromotionId(), amLoanMainInfo.getTenantId());
            loanConfirmRes.setPromotionId(prPromotionInfo.getPromotionId());
            loanConfirmRes.setPromotionDesc(prPromotionInfo.getPromotionDesc());
        }
        BigDecimal totalExemptAmount = repaymentPlanResList.stream().map(RepaymentPlanRes::getExemptAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        loanConfirmRes.setTotalExemptAmount(totalExemptAmount);
        return loanConfirmRes;
    }

    /**
     * 取消订单
     *
     * @param loanId
     * @return
     */
    @Override
    public CancelSaveBean cancelOrder(String loanId, String customerId, String tenantId, Date businessDate, String changeLimit) throws TxnBizException {
        CancelSaveBean saveBean = new CancelSaveBean();
        List<TlTransactionInfo> tlTransactionInfoList = new ArrayList<>();
        AmLoanMainInfo amLoanMainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndCusId(loanId, customerId, tenantId);
        //1.取消订单账户表
        AmLoanAccountInfo loanAccountInfo = extAmLoanAccountInfoMapper.selectByLoanId(loanId, customerId, tenantId);

        if (TransBizConstant.LOAN_STATUS_9.equals(loanAccountInfo.getAccountStatus())) {
            return saveBean;
        }

        AmLoanAccountInfo updateLoan = new AmLoanAccountInfo();
        updateLoan.setId(loanAccountInfo.getId());
        updateLoan.setCustomerId(customerId);
        updateLoan.setTenantId(tenantId);
        updateLoan.setAccountStatus(TransBizConstant.LOAN_STATUS_9);
        updateLoan.setCurrBalance(BigDecimal.ZERO);//余额
        updateLoan.setPrincipalBalance(BigDecimal.ZERO);//	本金余额
        updateLoan.setInterestBalance(BigDecimal.ZERO);//利息余额
        updateLoan.setPenaltyBalance(BigDecimal.ZERO);//罚息余额
        updateLoan.setCompoundBalance(BigDecimal.ZERO);//复利余额
        updateLoan.setFeeBalance(BigDecimal.ZERO);//服务费余额
        updateLoan.setRemainPrincipal(amLoanMainInfo.getLoanAmount());//剩余本金 所有未还本金（包含未抛部分） 贷款金额
        updateLoan.setAccruedInterest(BigDecimal.ZERO);//已计提未抛利息
        updateLoan.setAccruedPenalty(BigDecimal.ZERO);//已计提未抛罚息
        updateLoan.setAccruedCompound(BigDecimal.ZERO);//已计提未抛复利
        updateLoan.setPayoffDate(businessDate);//结清日期
        saveBean.setUpdateLoan(updateLoan);

        //2.取消还款计划
        List<AmRepaymentPlanInfo> amRepaymentPlanInfoList = extAmRepaymentPlanInfoMapper
                .selectRepaymentPlanInfoListByLoanIdAndStatus(loanId, null, customerId, tenantId);
        UnaryOperator<AmRepaymentPlanInfo> cancelPlan = plan -> {
            AmRepaymentPlanInfo updatePlan = new AmRepaymentPlanInfo();
            updatePlan.setId(plan.getId());
            updatePlan.setCustomerId(customerId);
            updatePlan.setTenantId(tenantId);
            updatePlan.setPlanStatus(TransBizConstant.LOAN_PLAN_STATUS_9);
            return updatePlan;
        };

        if (!CollectionUtils.isEmpty(amRepaymentPlanInfoList)) {
            List<AmRepaymentPlanInfo> updatePlanList = amRepaymentPlanInfoList.stream().map(cancelPlan).collect(Collectors.toList());
            saveBean.setUpdatePlanList(updatePlanList);
        }

        //3.取消贴息还款计划
        List<AmWaiveRepaymentPlanInfo> amWaiveRepaymentPlanInfoList = extAmWaiveRepaymentPlanInfoMapper
                .selectRepaymentPlanInfoListByLoanIdAndStatus(loanId, null, customerId, tenantId);
        UnaryOperator<AmWaiveRepaymentPlanInfo> cancelWaivePlan = plan -> {
            AmWaiveRepaymentPlanInfo updateWaivePlan = new AmWaiveRepaymentPlanInfo();
            updateWaivePlan.setId(plan.getId());
            updateWaivePlan.setCustomerId(customerId);
            updateWaivePlan.setTenantId(tenantId);
            updateWaivePlan.setPlanStatus(TransBizConstant.LOAN_PLAN_STATUS_9);
            return updateWaivePlan;
        };

        if (!CollectionUtils.isEmpty(amWaiveRepaymentPlanInfoList)) {
            List<AmWaiveRepaymentPlanInfo> updateWaivePlanList = amWaiveRepaymentPlanInfoList.stream().map(cancelWaivePlan).collect(Collectors.toList());
            saveBean.setUpdateWaivePlanList(updateWaivePlanList);
        }

        //3.取消交易账户
        List<AmAccountMainInfo> amAccountMainInfoList = extAmAccountMainInfoMapper.selectByStatusAndType(loanId, null, null, null, customerId, tenantId);
        UnaryOperator<AmAccountMainInfo> cancelAcct = acct -> {
            AmAccountMainInfo updateAcct = new AmAccountMainInfo();
            updateAcct.setId(acct.getId());
            updateAcct.setCustomerId(customerId);
            updateAcct.setTenantId(tenantId);
            updateAcct.setAccountStatus(TransBizConstant.ACCOUNT_STATUS_9);
            return updateAcct;
        };

        if (!CollectionUtils.isEmpty(amAccountMainInfoList)) {
            List<AmAccountMainInfo> updateAcctList = amAccountMainInfoList.stream().map(cancelAcct).collect(Collectors.toList());
            saveBean.setUpdateAcctList(updateAcctList);

            //生成本经账户交易
            // 获取本金账户
            Predicate<AmAccountMainInfo> principalAccountPredicate =
                    acct -> TransBizConstant.ONE.equals(acct.getBillingTenor()) && TransBizConstant.ACCOUNT_TYPE_06.equalsIgnoreCase(acct.getAccountType());
            List<AmAccountMainInfo> principalAcct = amAccountMainInfoList.stream().filter(principalAccountPredicate).collect(Collectors.toList());
            //根据取消本金账户生成交易信息
            TlTransactionInfo principalTrans = tlTransactionInfoService.buildTlTransactionInfo(principalAcct.get(0),
                    TransBizConstant.TRANSCATION_REVERSAL_FLAG_1);
            principalTrans.setPostingDate(businessDate);
            tlTransactionInfoList.add(principalTrans);
        }

        //4.取消累计交易账户
        List<AmInterestAccrualInfo> amInterestAccrualInfoList = extAmInterestAccrualInfoMapper.selectAllAccuAcct(loanId, customerId, tenantId, null, null);
        UnaryOperator<AmInterestAccrualInfo> cancelAccuAcct = accuAcct -> {
            AmInterestAccrualInfo updateAccuAcct = new AmInterestAccrualInfo();
            updateAccuAcct.setId(accuAcct.getId());
            updateAccuAcct.setCustomerId(customerId);
            updateAccuAcct.setTenantId(tenantId);
            updateAccuAcct.setAccountStatus(TransBizConstant.INTEREST_ACCRUAL_STATUS_9);
            return updateAccuAcct;
        };

        if (!CollectionUtils.isEmpty(amInterestAccrualInfoList)) {
            List<AmInterestAccrualInfo> updateAccuAcctList = amInterestAccrualInfoList.stream().map(cancelAccuAcct).collect(Collectors.toList());
            saveBean.setUpdateAccuAcctList(updateAccuAcctList);
        }

        //5.生成负向冲销GL流水
        List<TlGlInterfaceInfo> tlGlInterfaceInfoList = extTlGlInterfaceInfoMapper.selectAllGl(loanId, customerId, tenantId);
        UncheckedUnaryOperator<TlGlInterfaceInfo> cancelGL = gl -> glInterfaceService.buildTlGlInterfaceInfo(gl, businessDate);


        if (!CollectionUtils.isEmpty(tlGlInterfaceInfoList)) {
            List<TlGlInterfaceInfo> saveGlList = tlGlInterfaceInfoList.stream()
                    .map(CollectorsUtils.tranToUncheck(cancelGL))
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            saveBean.setSaveGlList(saveGlList);
        }

        //获取放款时交易信息
        TlTransactionInfo tlTransactionInfo = extTlTransactionInfoMapper.selectByLoanIdAndTxnCode(loanId,
                TransBizConstant.TXN_CODE_INSTSUM,
                customerId, tenantId);
        // 如果是转分期的则没有放款交易信息
        if (Objects.nonNull(tlTransactionInfo)) {
            //构建取消订单的交易信息流水
            TlTransactionInfo transactionInfo = tlTransactionInfoService.buildTlTransactionInfo(tlTransactionInfo, TransBizConstant.TXN_CODE_INSTSUM_REVOCATION,
                    TransBizConstant.TRANSCATION_REVERSAL_FLAG_1);
            transactionInfo.setPostingDate(businessDate);
            tlTransactionInfoList.add(transactionInfo);
        }
        saveBean.setTlTransactionInfoList(tlTransactionInfoList);

        if (Objects.isNull(changeLimit) || !Constant.NO_FLAG.equalsIgnoreCase(changeLimit)) {
            //恢复客户额度
            customerLimitInfoService.modifyCustomerLimit(tenantId, customerId, loanAccountInfo.getOrganizationId(),
                    loanAccountInfo.getChannel(), loanAccountInfo.getProductId(), loanAccountInfo.getRemainPrincipal(), amLoanMainInfo.getContractNumber());
        }

        //恢复优惠券
        if (TransBizConstant.WAIVE_TYPE_2.equals(amLoanMainInfo.getWaiveType())) {
            CmCustomerRightInfo updateCustRight = new CmCustomerRightInfo();
            updateCustRight.setId(amLoanMainInfo.getCustRightId());
            updateCustRight.setLoanId("");
            updateCustRight.setRightsStatus(CustomerConstant.RIGHTS_STATUS_0);
            updateCustRight.setCustomerId(amLoanMainInfo.getCustomerId());
            updateCustRight.setTenantId(amLoanMainInfo.getTenantId());
            saveBean.setUpdateCustRight(updateCustRight);
        }

        return saveBean;
    }

    /**
     * 账单日规则
     *
     * @param orgId    机构id
     * @param proId    产品id
     * @param loanDate 放款日期
     * @return 账单日
     */
    @Override
    public Integer getStatementDayByRule(String orgId, String proId, Date loanDate, String tenantId) throws TxnBizException {
        Map<String, Object> map = new HashMap<>();
        map.put(TransBizConstant.LOAN_RULE_BORROW_DATE, Integer.parseInt(DateUtils.getDay(loanDate)));  //借款日是什么
        map.put(TransBizConstant.LOAN_RULE_BORROW_MONTH, Integer.parseInt(DateUtils.getMonth(loanDate)));  //借款月分是什么
        RuleMatchReq ruleMatchReq = new RuleMatchReq(orgId, proId, TransBizConstant.PRO_STATEMENT_DAY_RULE_TYPE, map, tenantId);
        String statementDayString =
                (String) aviatorService.executeRuleResultMap(ruleMatchReq).get(TransBizConstant.LOAN_RULE_RES_KEY);

        Integer statementDay = TransBizConstant.LOAN_DATE.equals(statementDayString) ?
                Integer.parseInt(DateUtils.getDay(loanDate)) : Integer.parseInt(statementDayString);

        return statementDay;
    }


    /**
     * 生成营销记录
     *
     * @param customerSecondLevelRes api传递数据
     * @return 营销记录
     */
    private TlMarketingRecord buildTlMarketingRecord(CustomerFirstLevelRes customerFirstLevelRes, CustomerSecondLevelRes customerSecondLevelRes, BigDecimal loanAmount, String loanId, String seqNo) throws TxnException {
        CmCustomerFirstLevel customerFirstLevel = BeanMapping.copy(customerFirstLevelRes, CmCustomerFirstLevel.class);
        CmCustomerSecondLevel customerSecondLevel = BeanMapping.copy(customerSecondLevelRes, CmCustomerSecondLevel.class);
        //查询客户地址信息
        CmCustomerAddressInfo cond = new CmCustomerAddressInfo();
        cond.setAddressStatus(CustomerConstant.STATUS_NORMAL);
        cond.setCustomerId(customerSecondLevel.getCustomerId());
        cond.setChannel(customerSecondLevel.getChannel());
        cond.setTenantId(customerSecondLevel.getTenantId());
        List<CmCustomerAddressInfo> addressInfoList = extCmCustomerAddressInfoMapper.selectByCondSelective(cond);

        //查询客户授信信息
        List<CmCustomerLimitInfo> customerLimitInfoList = extCmCustomerLimitInfoMapper
                .selectCusLimitByCusIdAndOrgIdAndStatus(customerSecondLevel.getOrganizationId(), customerSecondLevel.getCustomerId(), CustomerConstant.CREDIT_LIMIT_STATUS_0, customerSecondLevel.getTenantId());

        MarketingRecordCreationBean marketingRecordCreationBean = new MarketingRecordCreationBean();
        marketingRecordCreationBean.setCustomerFirstLevel(customerFirstLevel);
        marketingRecordCreationBean.setCustomerSecondLevel(customerSecondLevel);
        marketingRecordCreationBean.setAddressInfoList(addressInfoList);
        marketingRecordCreationBean.setCustomerLimitInfoList(customerLimitInfoList);
        marketingRecordCreationBean.setStep(CustomerConstant.MARKET_STEP_3);
        marketingRecordCreationBean.setSeqNo(seqNo);
        TlMarketingRecord result = customerService.generateMarketingRecord(marketingRecordCreationBean);

        if (null != result) {
            try {
                result.setId(segmentService.getId(Constant.TL_MARKETING_RECORD));//id
            } catch (SegmentException e) {
                logger.error("主键生成错误", e);
                throw new TxnException(TxnRespCode.ERROR.getUserTips());
            }
            result.setLoanAmount(loanAmount);
            result.setLoanId(loanId);
        }
        return result;
    }

    @Override
    public void saveCancleBean(CancelSaveBean cancelSaveBean) {

        if (null != cancelSaveBean.getUpdateLoan()) {
            extAmLoanAccountInfoMapper.updateByPrimaryKey(cancelSaveBean.getUpdateLoan());
        }


        if (CollectionUtils.isNotEmpty(cancelSaveBean.getUpdatePlanList())) {
            extAmRepaymentPlanInfoMapper.batchUpdatePlan(cancelSaveBean.getUpdatePlanList());
        }

        if (CollectionUtils.isNotEmpty(cancelSaveBean.getUpdateWaivePlanList())) {
            extAmWaiveRepaymentPlanInfoMapper.batchUpdatePlan(cancelSaveBean.getUpdateWaivePlanList());
        }


        if (CollectionUtils.isNotEmpty(cancelSaveBean.getUpdateAcctList())) {
            extAmAccountMainInfoMapper.batchUpdateAccount(cancelSaveBean.getUpdateAcctList());
        }

        if (CollectionUtils.isNotEmpty(cancelSaveBean.getUpdateAccuAcctList())) {
            extAmInterestAccrualInfoMapper.batchUpdateInterestAccrualInfo(cancelSaveBean.getUpdateAccuAcctList());
        }


        if (CollectionUtils.isNotEmpty(cancelSaveBean.getSaveGlList())) {
            extTlGlInterfaceInfoMapper.batchInsertSelective(cancelSaveBean.getSaveGlList());
        }

        if (CollectionUtils.isNotEmpty(cancelSaveBean.getTlTransactionInfoList())) {
            extTlTransactionInfoMapper.batchInsert(cancelSaveBean.getTlTransactionInfoList());
        }

        if (null != cancelSaveBean.getUpdateCustRight()) {
            CmCustomerRightInfo updateRightInfo = cancelSaveBean.getUpdateCustRight();
            extCmCustomerRightInfoMapper.updateCustRight(updateRightInfo.getId(), updateRightInfo.getLoanId(), updateRightInfo.getRightsStatus(), updateRightInfo.getTenantId(), updateRightInfo.getCustomerId());
        }

    }

    @Override
    public Integer getPaymentDayByRule(String orgId, String proId, Date loanDate, String tenantId) throws TxnBizException {
        Map<String, Object> map = new HashMap<>();
        map.put(TransBizConstant.LOAN_RULE_BORROW_DATE, Integer.parseInt(DateUtils.getDay(loanDate)));  //借款日是什么
        map.put(TransBizConstant.LOAN_RULE_BORROW_MONTH, Integer.parseInt(DateUtils.getMonth(loanDate)));  //借款月分是什么
        RuleMatchReq ruleMatchReq = new RuleMatchReq(orgId, proId, TransBizConstant.PRO_PAY_DAY_RULE_TYPE, map, tenantId);
        String paymentDayString =
                (String) aviatorService.executeRuleResultMap(ruleMatchReq).get(TransBizConstant.LOAN_RULE_RES_KEY);

        Integer paymentDay = TransBizConstant.LOAN_DATE.equals(paymentDayString) ?
                Integer.parseInt(DateUtils.getDay(loanDate)) : Integer.parseInt(paymentDayString);

        return paymentDay;
    }
}
